package io.lvdaxian.mybatis16.scripting.xmltags;

import io.lvdaxian.mybatis16.builder.SqlSourceBuilder;
import io.lvdaxian.mybatis16.mapping.BoundSql;
import io.lvdaxian.mybatis16.mapping.SqlSource;
import io.lvdaxian.mybatis16.session.Configuration;

import java.util.Map;

/**
 * 动态sql 解析
 *
 * @author lihh
 */
public class DynamicSqlSource implements SqlSource {
  
  // 配置信息
  private Configuration configuration;
  // sql node 节点
  private SqlNode rootSqlNode;
  
  public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
    this.configuration = configuration;
    this.rootSqlNode = rootSqlNode;
  }
  
  @Override
  public BoundSql getBoundSql(Object parameterObject) {
    // 生成一个 DynamicContext 动态上下文
    DynamicContext context = new DynamicContext(configuration, parameterObject);
    // SqlNode.apply 将 ${} 参数替换掉，不替换 #{} 这种参数
    rootSqlNode.apply(context);
    
    // 调用 SqlSourceBuilder
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
    
    // SqlSourceBuilder.parse 这里返回的是 StaticSqlSource，解析过程就把那些参数都替换成?了，也就是最基本的JDBC的SQL语句。
    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
    
    // SqlSource.getBoundSql，非递归调用，而是调用 StaticSqlSource 实现类
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
      boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
    }
    return boundSql;
  }
  
}
